#include "StdAfx.h"
#include "ShaderManagerOpenGL.h"


namespace banknamespace
{
	ShaderManagerOpenGL::ShaderManagerOpenGL(void)
	{
		// init attributeMap
		attributeMap["SATT_POSITION"] = 0;
		attributeMap["SATT_TEXCOORD0"] = 1;
		attributeMap["SATT_TEXCOORD1"] = 2;
		attributeMap["SATT_NORMAL"] = 3;
		attributeMap["SATT_TANGENT"] = 4;
		attributeMap["SATT_BITANGENT"] = 5;
		attributeMap["SATT_TANGENT4F"] = 6;
	}


	ShaderManagerOpenGL::~ShaderManagerOpenGL(void)
	{
		for (unsigned int i = 0; i < shaderProgArr.size(); ++i)
		{
			delete shaderProgArr[i];
		}
	}

	int ShaderManagerOpenGL::createProgram(const char* programName, std::vector<attrStruct>& attrStr, std::vector<const char*>& uniformString)
	{
		ShaderProgram* tmpProgram = new ShaderProgram;
		std::string name = programName;
		std::string vsPath = "Shader_GLSL/" + name + ".vs";
		std::string psPath = "Shader_GLSL/" + name + ".ps";
		tmpProgram->createProgram(vsPath, psPath);

		// bind attributes
		std::vector<attrStruct> tmpVec;
		for (unsigned int i = 0; i < attrStr.size(); ++i)
		{
			attrStruct tmpStruct = attrStr[i];
			tmpStruct.id = attributeMap[attrStr[i].name];
			tmpVec.push_back(tmpStruct);
			glBindAttribLocation( tmpProgram->getProgramId(), attributeMap[attrStr[i].name], attrStr[i].name );
		}
		attributeProg.push_back(tmpVec);
		glLinkProgram( tmpProgram->getProgramId() );
		
		glUseProgram( tmpProgram->getProgramId() );
		currentProgram = shaderProgArr.size();

		shaderProgArr.push_back(tmpProgram);
		
		return currentProgram;
	}
	
	void ShaderManagerOpenGL::useProgram(int progID)
	{
		glUseProgram( shaderProgArr[progID]->getProgramId() );
		currentProgram = progID;
	}
	int ShaderManagerOpenGL::getLocation(const char* name)
	{
		return glGetUniformLocation( shaderProgArr[currentProgram]->getProgramId(), name );
	}
	void ShaderManagerOpenGL::setVariable(int ulocation, shaderType type, void* value)
	{
		switch (type)
		{
		case S_MAT4 : 
			{
				glUniformMatrix4fv( ulocation, 1, 0, reinterpret_cast<float*>( value ) ); 
				break;
			}
		case S_VEC4 : 
			{
				glUniform4fv( ulocation, 1, reinterpret_cast<float*>( value ) ); 
				break;
			}
		case S_VEC3 : 
			{
				glUniform3fv( ulocation, 1, reinterpret_cast<float*>( value ) );
				break;
			}
		case S_FLOAT : 
			{
				glUniform1f( ulocation, *(reinterpret_cast<float*>( value )) );
				break;
			}
		case S_TEXTURE : 
			{
				glUniform1i( ulocation, *(reinterpret_cast<int*>( value )) );
				break;
			}
		default: assert(0); break;
		}
	}

}
